被称为一个漂亮的Asp.net MVC应用,从代码角度来看,我认为得满足这三点:

1. 使用依赖注入框架。

2. 不要直接依赖Cache, HttpContext等。

3. View中不要条件逻辑。

  当然不只是这三点,还有很多。我个人拿它们出来,是认为这些很重要但是经常被忽视。

 

  对于第1点,优点在于松耦合,可测试性很好。如果在Controller里面想要使用某些Service,要么new出来,要么用单例的形式,如UserService.Instance,这样想对Controller写单元测试都不容易,它和这些Service耦合太紧密,无法将这些Service替换成Stub实现。因此,松耦合是必须的。要实现这个功能,必须让依赖注入框架来创建Controller,才有可能注入依赖并组装对象。MVC里面有一个ControllerFactory的东西,可以使用来达到这个目的。

  a. 写一个类,继承自DefaultControllerFactory,例如 UnityControllerFactory : DefaultControllerFactory

  b. 覆盖方法GetControllerInstance,使用依赖注入框架来创建Conroller

  c. 修改Global.asax.cs, 在Application_Start内注册使用自己的ControllerFactory,

     ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory())

  d. 对Controller进行构造函数注入,例如:

      public class UserController : Controller

      {

           public UserController(IUserService, userService, IMessageService messageService)

           …

       }

    从现在开始,所有的Controller都是通过依赖注入框架来创建的,新增的Service就在依赖注入框架里面注册,Controller要使用哪些Service就往构造函数里加,反正框架会注入进来。

 

    第2点, 类如HttpContext.Current.Session[“xxx”] = …, HttpContext.Current.Cache.Insert…此样的代码充斥在各个角落。有问题吗?还是老问题,可测试性,可替换性。

    像HttpContext这种东西,几乎是不能Mock或者Stub的,只要代码中使用了HttpContext,可以说它就没法做单元测试。为什么很多人都会这么用呢,一个原因是图方便图简单,二是没有写单元测试。要用Session直接用就好了,封装一下再用多麻烦啊,这就是图简单。

    解法很简单,对HttpContext进行封装,例如ISessionProvider, ICacheProvider,然后通过依赖注入框架,注入到Controller中去,这样的结果是代码可测试性高,而且想改变Cache机制也很方便。

    意识不够。什么意识?让代码松耦合的意识。使用静态方法,静态变量,直接new依赖的对象,这些都是松耦合的反例。我们写代码的时候要规避它们。即使我们不用TDD(极端一点来说,现在不写单元测试),脑子里也要清楚记得,面向对象的法则、松耦合的一些原则等等,然后反应到代码上去。

    这一点,记得好像园子里以前有人提到过。

 

    最后一点,View中不写条件逻辑。View中一旦加入条件判断,就会使得代码特别难以维护,难以理解。如果在aspx文件中,看到以下的代码:

   <% if (条件1) { %>

    <div>

      …

      <% if(某某条件) { %>

       …

       <% } %>

     </div>

   <%} else if (条件2) { %>

      …

   <% } else { %>

      …

   <% } %>

   这样的View让人很怕去改,生怕哪里改错了而自己又不知道。因为它写的太混乱,逻辑和显示穿插在一起,如果再混着一些动态的html元素,那就真的只能谁写的谁来弄。

   我们可以怎样做呢?如果是比较复杂的条件逻辑,就放到Controller里面去做,然后返回不同的View。这样View又很简单,这些逻辑又可以被测试。没有谁规定,一个Action只能对应一个View。跟Class的道理一样,Class职责过多,就得进行拆分。View的逻辑过于复杂也得进行拆分。

  这么拆分以后,有可能会出现几个View有重复的部分。那就具体情况具体解决了,可以使用ViewHelper,也可以把重复的东西再独立出来,不同的View来复用。记住,View是代码的一部分,不要觉得涉及到Html的部分乱就乱点。View也是需要持续被重构的。

  这一篇着重强调的是,漂亮的代码有良好的可测试性。

 posted on 2009-11-01 22:33  紫色阴影  阅读(3804)  评论(29编辑  收藏  举报
我要啦免费统计